package com.diagrammer.convertor
{
	import com.diagrammer.render.LineRender;
	import com.diagrammer.render.NodeRender;
	import com.diagrammer.render.factory.IRenderFactory;
	import com.diagrammer.render.factory.RenderFactory;
	import com.diagrammer.vo.LineVO;
	import com.diagrammer.vo.NodeVO;

	/**
	 * 将节点和线条VO转换成相应的组件render
	 * 
	 * @author Dwei <b>2012-02-13</b>
	 * 
	 */	
	public class RenderConvertor
	{
//============================================================================
//parameter
//============================================================================
		private const _nodesMap:Object = {};
		
		private const _linesMap:Object = {};
		
		private var _factory:IRenderFactory;
		/** 替换数据时，将已存在的lineRender做为备份载体提供给新的VO数据 */		
		protected const nodesLibrary:Array = [];
		/** 替换数据时，将已存在的lineRender做为备份载体提供给新的VO数据 */		
		protected const linesLibrary:Array = [];
//============================================================================
//constructor
//============================================================================
		public function RenderConvertor()
		{
			_factory = new RenderFactory();
		}
//============================================================================
//public
//============================================================================
		/**
		 * 新增节点，在记录中添加一个节点Render。
		 * 如果已存在相同标识的NodeRender，将不会新创建NodeRender对象，而是直接将存在的NodeRender.vo替换成传入的NodeVO
		 * @param value
		 * @return 新增的节点Render，若新增失败，返回null。
		 * 
		 */		
		public function addNode(value:NodeVO):NodeRender
		{
			if (!value) return null;
			//获取节点Render
			var result:NodeRender = nodesLibrary.shift();//isNodeExist(value.ID)?nodesMap[value.ID]:factory.getNodeRender(value);
			if (!result)
			{
				result = factory.getNodeRender(value);
				trace (" 创建NodeRender:" + value.ID);
			}
			//判断是否支持创建该NodeVO的NodeRender
			if (!result)
			{
				trace ("新增节点Render失败：节点Render工厂不支持该数据-" + value.ID);
				return null;
			}
			//初始化节点Render
			result.vo = value;
			
			//保存节点Render
			nodesMap[value.ID] = result;
			return result;
		}
		
		/**
		 * 删除节点，从记录中删除该节点Render
		 * @param id
		 * @return 返回删除成功的节点Render，失败则返回null
		 * 
		 */		
		public function removeNode(id:String):NodeRender
		{
			if (!isNodeExist(id))
			{
				trace ("删除节点Render失败：节点Render不存在-" + id);
				return null;
			}
			var result:NodeRender = nodesMap[id];
			delete nodesMap[id];
			trace ("删除NodeRender:" + id);
			return result;
		}
		
		/**
		 * 新增线条，在记录中添加一个线条Render。
		 * 如果已存在相同标识的LineRender，将不会新创建LineRender对象，而是直接将存在的LineRender.vo替换成传入的LineVO
		 * @param value
		 * @return 新增的线条Render，若新增失败，返回null
		 * 
		 */		
		public function addLine(value:LineVO):LineRender
		{
			if (!value) return null;
			//获取线条Render
			var result:LineRender = linesLibrary.shift();//isLineExist(value.ID)?linesMap[value.ID]:factory.getLineRender(value);
			if (!result)
			{
				result = factory.getLineRender(value);
				trace ("创建LineRender:" + value.ID);
			}
			//判断是否支持创建该LineVO的LineRender
			if (!result)
			{
				trace ("新增线条Render失败：线条Render工厂不支持该数据-" + value.ID);
				return null;
			}
			//判断线条关联的起始或者结束NodeRender是否存在
			if (!isNodeExist(value.fromID) || !isNodeExist(value.toID))
			{
				trace ("新增线条Render失败：线条关联的起始或者结束节点Render不存在-" + value.ID);
				return null;
			}
			//初始化线条Render
			result.vo = value;
			
			//保存线条Render
			linesMap[value.ID] = result;
			return result;
		}
		
		/**
		 * 删除线条，从记录中删除该线条Render
		 * @param id
		 * @return 返回删除成功的线条Render，失败则返回null
		 * 
		 */		
		public function removeLine(id:String):LineRender
		{
			if (!isLineExist(id))
			{
				trace ("删除线条Render失败：线条Render不存在-" + id);
				return null;
			}
			var result:LineRender = linesMap[id];
			delete linesMap[id];
			trace ("删除LineRender:" + id);
			return result;
		}
		
		/**
		 * 判断是否存在与传入的节点标识相同的节点
		 * @param id 节点标识
		 * @return 
		 * 
		 */		
		public function isNodeExist(id:String):Boolean
		{
			return Boolean(nodesMap[id]);
		}
		
		/**
		 * 判断是否存在与传入的线条标识相同的线条
		 * @param id 线条标识
		 * @return 
		 * 
		 */		
		public function isLineExist(id:String):Boolean
		{
			return Boolean(linesMap[id]);
		}
//============================================================================
//protected
//============================================================================
		
//============================================================================
//getter/setter
//============================================================================
		/**
		 * 设置VO转换器，并将VO转换成对应的Render
		 * @param value VO转换器对象
		 * 
		 */		
		public function set voConvertor(value:VOConvertor):void
		{
			if (!value) return;
			var key:String;
			//保存当前节点Render做为备份节点Render
			for (key in nodesMap)
			{
				nodesLibrary.push(nodesMap[key]);
			}
			var nodeRender:NodeRender;
			//删除所有节点Render记录
			for each (nodeRender in nodesLibrary)
			{
				delete nodesMap[nodeRender.vo.ID];
			}
			var keys:Array = [];
			//创建节点Render记录
			for each (key in value.nodes)
			{
				if (!addNode(value.nodesMap[key] as NodeVO))
					keys.push(key);
			}
			//清空节点Render备份
			nodesLibrary.splice(0, nodesLibrary.length);
			var keyInner:String;
			var keysLine:Array;
			//删除未转换成NodeRender的NodeVO记录
			for each (key in keys)
			{
				keysLine = NodeVO(value.nodesMap[key]).lines.concat();
				//删除节点关联的线条
				for each (keyInner in keysLine)
				{
					//删除线条关联的节点之间的关系
					value.unRelateNodes(keyInner);
					//删除线条VO的记录
					value.removeLine(keyInner);
				}
				//删除NodeVO记录
				value.removeNode(key);
			}
			//================================================================
			//保存当前线条Render做为备份线条Render
			for (key in linesMap)
			{
				linesLibrary.push(linesMap[key]);
			}
			var lineRender:LineRender;
			//删除所有线条Render记录
			for each (lineRender in linesLibrary)
			{
				delete linesMap[lineRender.vo.ID];
			}
			keys = [];
			//创建节点Render记录
			for each (key in value.lines)
			{
				if (!addLine(value.linesMap[key] as LineVO))
					keys.push(key);
			}
			//清空线条Render备份
			linesLibrary.splice(0, linesLibrary.length);
			//删除未转换成LineRender的LineVO记录
			for each (key in keys)
			{
				value.removeLine(key);
			}
		}

		/**
		 * 所有节点标识-节点render映射集合
		 */
		public function get nodesMap():Object
		{
			return _nodesMap;
		}

		/**
		 * 所有线条标识-线条render映射集合
		 */
		public function get linesMap():Object
		{
			return _linesMap;
		}

		/**
		 * 创建节点Render对象的工厂类，忽略null，默认-com.diagrammer.view.spark.factory.RenderFactory
		 */
		public function get factory():IRenderFactory
		{
			return _factory;
		}

		/**
		 * @private
		 */
		public function set factory(value:IRenderFactory):void
		{
			if (!value) return;
			_factory = value;
		}


	}
}